moddbfandomcom-20200213-history
Singleton Pattern
The singleton pattern is implemented by creating a class with a method that creates a new instance of the object if one does not exist. If one does exist it returns a reference to the object that already exists. To make sure that the object cannot be instantiated any other way the constructor is made either private or protected. Definition Problem 1"Ensure a class only has one instance, and provide a global point of access to it." Context # All objects need access to a single instance of a class # It is required that no additional instances of the class are created Solution # Define a class with a private constructor # The class constructs a single instance of itself # Supply a static method that returns a reference to the single instance UML Diagram frame|none|UML Diagram of the Singleton Pattern A Singleton Class Template in C++ template class Singleton { public: static T *Instance(); // Create an instance of the object static T &ref_getSingleton(); // Get a reference to the object static T *ptr_getSingleton(); // Get a pointer to the object protected: Singleton(); // notice that the constructor is NOT public private: static T *m_instance; // The actual object }; This is the singleton factory, and it's not so big but can be a bit confusing. The implementation of the getSingleton functions returns the instance of the object. Creating a Singleton Object To create an instance of an object as singleton just use the static properties of this class: Singleton::Instance(); Comment surely the above violates the pattern, due to being able to create a separate none singleton Application instance? To use a singleton version of a class it will have to have one instance, so it would be wise to do a check to see if the instance is created before returning it, and create it if it does not exist. This means that we will never need an actual member in any class to hold the instance, it's done by the singleton template, I use it for my mouse and keyboard listeners, because there are not often you have the opportunity to have multiples of those. To access an instance of the class you just use one of the getSingleton functions. Singleton::ptr_getSingleton(); If there is an instance of this it is returned otherwise an instance should be created. Example of how to use an instanced singleton (Edit note: I did write this in a confusing way, and did not really understand what I was trying to explain so here are hopefully a better way to explain how to use it) To give an easy example of how to work with the design pattern I will use this easy keyboard listener: class Keyboard_Listener { public: void keyPressed(const int key) {m_keyskey = true;} // sets a key status to pressed bool isKeyPressed(const int key) {return m_keyskey;} // checks a given keys status private: bool m_keys256; // not sure how many there are, just a guess }; Assume that there are some function handling user interaction (i.e. the Win32 uses the window procedure). If a user press the 'k' key and the keyboard listener should get a notice about it, I use the singleton as a tool to inform the one instance of Keyboard_Listener. In pseudo-code it would be something like: if(key_pressed = 'k') Singleton::ptrGetSingleton()->keyPressed('k'); To check this in the application I use the singleton to ask if the key is pressed, in pseudo code: if(Singleton::ptrGetSingleton()->isKeyPressed('k')) do some stuff; Putting it Together This is a small program that makes use of the previous mentioned classes: int main(void) { int input; Singleton::Instance(); while(true) { cin >> input; Singleton::ptrGetSingleton()->keyPressed(input); if(Singleton::ptrGetSingleton()->isKeyPressed('q')) { cout << "you pressed q on your keyboard, exiting..." << endl; break; } } return 0; } That last example just shows some way of using the singleton, when I know that heavy use will be conducted I create a pointer to hold the instance, consider: Singleton::ptrGetSingleton()->keyPressed(input); In opposition to: Keyboard_Listener *k; k = Singleton::ptrGetSingleton(); k->keyPressed; I believe the latter is a bit easier to work with and the code will be more readable. You can also use a typedef-statement to make a shorthand notation of the singleton class. That way, you can use a placeholder name of your own choice to point to singleton class. typedef Singleton::Instance() SingletonKeyboardListener; #define KeyboardListener SingletonKeyboardListener::ptrGetSingleton() Calling the keyPressed() function will then look like this KeyboardListener->keyPressed(input); The compiled code will actually look like the following SingletonKeyboardListener::ptrGetSingleton()->keyPressed(input); With KeyboardListener being replaced by SingletonKeyboardListener::ptrGetSingleton(). You only see the placeholder name, however, so the readability will be improved. Be aware that if you're using Microsoft Visual Studio, the IntelliSense function might not be able to parse this setup. Additional Information * The singleton pattern at Wikipedia * Article discussing problems/solutions of the Singleton from at Gamedev.Net * Article on the Singleton Class Cluster from Gamedev.Net * 3 Articles on why not to use singletons Washu Gamedev.net Blog * Article on why Singletons are usually a bad idea Scientific Ninja's Website 1Erich Gamma et al, "Design Patterns: elements of reusable object-oriented software", Addison Wesley (1995) : external C++ implementation Category:Tutorial Category:C plus plus Category:Design Patterns Category:Programming Techniques Category:Code Design Category:Object-Oriented Programming